#include "world.h"

World::World(const int& width, const int& height, const int& sectors_width,  const int& sectors_height)
{
	w = width;
	h = height;

	sectors_w = sectors_width;
	sectors_h = sectors_height;

	sector_w = (double)width/(double)sectors_w;
	sector_h = (double)height/(double)sectors_h;

	objects = new vector<Object*>;//[sectors_w*sectors_h];
}

World::~World()
{
	//for(int i = 0; i < sectors_w * sectors_h; i++)
	//{
		for(unsigned int j = 0;j < objects->size(); j++)
		{
			delete  (*objects)[j];
		}
	//}
	delete objects;
}

void World::Add_object(Object* new_object)
{
	/*unsigned int sector_x = (unsigned int) (new_object->position.Get_x()/sector_w);
	unsigned int sector_y = (unsigned int) (new_object->position.Get_y()/sector_y);

	if(sector_x < sectors_w && sector_y < sectors_h)
		objects[sector_y*sectors_w + sector_x].push_back(new_object);
	else
		delete new_object;*/
	objects->push_back(new_object);

}

void World::Frame_calculate()
{
	//for(int i = 0; i < sectors_w * sectors_h; i++)
	//{
		for(unsigned int j = 0;j < objects->size(); j++)
		{
			(*objects)[j]->Frame_calculate();

			// check the object, if it should be removed
			if((*objects)[j]->remove)
			{
				delete (*objects)[j];
				objects->erase(objects->begin()+j);
				j--; // recheck
				continue;
			}

			// the new position of the object
			Vect2D new_position = (*objects)[j]->position + (*objects)[j]->speed;

			//border checks
			if(new_position.Get_x() < 0)
			{
				new_position.Set_x(0);
				(*objects)[j]->speed.Set_x(0);
			}
			else
			if(new_position.Get_x() > w)
			{
				new_position.Set_x(w);
				(*objects)[j]->speed.Set_x(0);
			}

			if(new_position.Get_y() < 0)
			{
				new_position.Set_y(0);
				(*objects)[j]->speed.Set_y(0);
			}
			else
			if(new_position.Get_y() > h)
			{
				new_position.Set_y(h);
				(*objects)[j]->speed.Set_y(0);
			}

			// poor collision detection and response
			for(unsigned int i = 0; i < objects->size(); i++)
			{
				if(j == i)
					continue;

				Vect2D diff_vector = new_position - (*objects)[i]->position;
				if(diff_vector.Get_lenght() < (*objects)[j]->border + (*objects)[i]->border)
				{

						Vect2D tmp = (*objects)[j]->speed;
						(*objects)[j]->speed = (*objects)[i]->speed;
						(*objects)[i]->speed = tmp;

						(*objects)[j]->Hit((*objects)[i]->Hit());
						(*objects)[i]->Hit((*objects)[j]->Hit());

				}
			}
			// set the new position
			(*objects)[j]->position = new_position;

		}


	//}
}

void World::Draw(SDL_Surface* screen, const Vect2D& camera_position)
{
	//unsigned int sector_x = (unsigned int) (camera_position.Get_x()/sector_w);
	//unsigned int sector_y = (unsigned int) (camera_position.Get_y()/sector_y);
	for(unsigned int j = 0;j < objects->size(); j++)
		{
			(*objects)[j]->Draw(screen, camera_position);
		}
}


void World::Draw_borders(SDL_Surface* screen, const Vect2D& camera_position, int color)
{
	for(unsigned int j = 0;j < objects->size(); j++)
		{
			(*objects)[j]->Draw_border(screen, camera_position, color);
		}
}

int World::Get_number_objects()
{
	return objects->size();
}
